
package com.joysuch.wwyt.quartz.risk;

import com.joysuch.wwyt.bp.entity.InspectExceptionAlarmMesage;
import com.joysuch.wwyt.bp.mapper.InspectExceptionAlarmMesageMapper;
import com.joysuch.wwyt.bp.repository.BpDepartDao;
import com.joysuch.wwyt.core.entity.BaseConfig;
import com.joysuch.wwyt.core.enums.BaseConfigCodes;
import com.joysuch.wwyt.core.quartz.ResetTimeSequenceBizCodesSeedJob;
import com.joysuch.wwyt.core.repository.BaseConfigDao;
import com.joysuch.wwyt.core.repository.BaseUserDao;
import com.joysuch.wwyt.core.service.BaseConfigService;
import com.joysuch.wwyt.mh.bean.MhGradingAlarmBean;
import com.joysuch.wwyt.mh.bean.MhMonitoringPointBean;
import com.joysuch.wwyt.mh.dto.MhGradingAlarmDto;
import com.joysuch.wwyt.mh.entity.MhAlarmLimitConfig;
import com.joysuch.wwyt.mh.entity.MhAlarmRecord;
import com.joysuch.wwyt.mh.entity.MhGradingAlarm;
import com.joysuch.wwyt.mh.mapper.MhGradingAlarmMapper;
import com.joysuch.wwyt.mh.repository.MhAlarmMessageDao;
import com.joysuch.wwyt.mh.service.MhAlarmLimitConfigService;
import com.joysuch.wwyt.mh.service.MhAlarmRecordService;
import com.joysuch.wwyt.mh.service.MhGradingAlarmService;
import com.joysuch.wwyt.mh.service.MhMonitoringPointService;
import com.joysuch.wwyt.risk.EvaluationPlanStrategies;
import com.joysuch.wwyt.risk.entity.RiskDistrict;
import com.joysuch.wwyt.risk.entity.RiskEvaluationPlan;
import com.joysuch.wwyt.risk.entity.RiskPoint;
import com.joysuch.wwyt.risk.repository.RiskDistrictDao;
import com.joysuch.wwyt.risk.repository.RiskEvaluationPlanDao;
import com.joysuch.wwyt.risk.repository.RiskPointDao;
import com.joysuch.wwyt.risk.service.RiskDistrictService;
import com.joysuch.wwyt.workflow.WorkFlowConstants;
import com.joysuch.wwyt.workflow.entity.WorkFlowProcess;
import com.joysuch.wwyt.workflow.entity.WorkFlowTask;
import com.joysuch.wwyt.workflow.enums.WorkFlowStatusEnum;
import com.joysuch.wwyt.workflow.repository.WorkFlowTaskDao;
import com.joysuch.wwyt.workflow.service.WorkFlowMenuService;
import com.joysuch.wwyt.workflow.service.WorkFlowProcessService;
import com.joysuch.wwyt.workflow.service.WorkFlowTaskProcessListService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.utils.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.transaction.Transactional;
import java.time.LocalDateTime;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * 定时任务实现如下功能:
 * <ul>
 * <li>1. 加载所有需要在当天重新评估的任务计划 (RiskEvaluationPlan.nextEvaluationTime为当天)</li>
 * <li>2. 如果是风险点评估计划，则将该风险点的jha,scl,riskLevel都置为空，同时更新所属风险区域(RiskDistrict)的风险级别</li>
 * <li>3. 如果是风险区域评估计划，则将该区域的固有风险评估置为空,riskLevel置空，不更新该风险区域风险级别（该区域下还包含风险点)</li>
 * </ul>
 *
 * @author zhangxiaohuan
 * @company huanke
 * @date 2019年12月15日 下午12:35:52
 * @since
 *
 */
@Service
@Slf4j
public class RiskEvaluationPlanJob {

    private static final Logger logger = LoggerFactory.getLogger(ResetTimeSequenceBizCodesSeedJob.class);

    @Autowired
    private RiskPointDao riskPointDao;
    @Autowired
    private RiskDistrictDao riskDistrictDao;
    @Autowired
    private RiskDistrictService riskDistrictService;
    @Autowired
    private RiskEvaluationPlanDao riskEvaluationPlanDao;
    @Autowired
    private BpDepartDao bpDepartDao;
    @Autowired
    private MhAlarmMessageDao mhAlarmMessageDao;
    @Autowired
    private BaseUserDao baseUserDao;
    @Autowired
    private InspectExceptionAlarmMesageMapper inspectExceptionAlarmMesageMapper;
    @Autowired
    private BaseConfigDao baseConfigDao;
    @Autowired
    private MhGradingAlarmService mhGradingAlarmService;
    @Autowired
    private WorkFlowMenuService workFlowMenuService;
    @Autowired
    private WorkFlowProcessService workFlowProcessService;
    @Autowired
    private WorkFlowTaskProcessListService workFlowTaskProcessListService;
    @Autowired
    private WorkFlowTaskDao workFlowTaskDao;
    @Autowired
    private MhGradingAlarmMapper mhGradingAlarmMapper;

    @Resource
    private MhAlarmRecordService alarmRecordService;

    @Resource
    private MhAlarmLimitConfigService alarmLimitConfigService;

    @Resource
    private MhMonitoringPointService mhMonitoringPointService;
    @Autowired
    private BaseConfigService baseConfigService;


    @Transactional
    @Scheduled(cron = "0 30 1 * * ?")
    public void check() {
        try {
            logger.info("开始处理评估计划");
            // quatz使用的是独立的线程，不会包含有Context中相关信息，所以不会被拦截，添加tenentId,orgCode字段。查询出的是所有租户的数据
            Date startTime = getTodayStartTime();
            Date endTime = getTodayEndTime();
            List<RiskEvaluationPlan> list = riskEvaluationPlanDao.findByNextEvaluationTimeBetween(startTime, endTime);
            logger.info("待处理的到期评估计划:" + list.size());
            for (RiskEvaluationPlan plan : list) {
                try {
                    process(plan);
                } catch (Exception e) {
                    logger.error("处理评估计划#" + plan.getId() + "出错", e);
                }
            }
            logger.info("评估计划处理完成");
        } catch (Exception e) {
            logger.error("评估计划出错", e);
        }
    }

    private void process(RiskEvaluationPlan plan) {
        if (plan.getRiskDistrictId() != null) {
            processDistrictEvaluation(plan);
        } else if (plan.getRiskPointId() != null) {
            processRiskPointEvaluation(plan);
        }
    }

    private void processRiskPointEvaluation(RiskEvaluationPlan plan) {
        // 重置风险点的评估状态
        RiskPoint one = riskPointDao.getOne(plan.getRiskPointId());
        one.setRiskLevel(null);
        one.setJhaEvaluationState(0);
        one.setSclEvaluationState(0);
        one.setRiskPointEvaluationJha(null);
        one.setRiskPointEvaluationScl(null);
        riskPointDao.save(one);
        if (one.getRiskDistrict() != null) {
            // 更新区域风险评级
            riskDistrictService.updateDistrictRiskLevel(one.getRiskDistrict().getId());
        }
        // 更新评估假话的下一次评估时间
        updatePlanNextEvaluationTime(plan);

    }

    private void updatePlanNextEvaluationTime(RiskEvaluationPlan plan) {
        EvaluationPlanStrategies strategies = EvaluationPlanStrategies.findByCode(plan.getStrategy());
        Calendar c = Calendar.getInstance();
        c.setTime(plan.getNextEvaluationTime());
        if (strategies == EvaluationPlanStrategies.YEAR) {
            c.add(Calendar.YEAR, 1);
            plan.setNextEvaluationTime(c.getTime());
        } else if (strategies == EvaluationPlanStrategies.HALF_YEAR) {
            c.add(Calendar.MONTH, 6);
            plan.setNextEvaluationTime(c.getTime());
        } else if (strategies == EvaluationPlanStrategies.SEASON) {
            c.add(Calendar.MONTH, 3);
            plan.setNextEvaluationTime(c.getTime());
        } else if (strategies == EvaluationPlanStrategies.MONTH) {
            c.add(Calendar.MONTH, 1);
            plan.setNextEvaluationTime(c.getTime());
        } else if (strategies == EvaluationPlanStrategies.WEEK) {
            c.add(Calendar.WEEK_OF_YEAR, 1);
            plan.setNextEvaluationTime(c.getTime());
        } else if (strategies == EvaluationPlanStrategies.FIXED) {
            // 不更新该计划
            // plan.setNextEvaluationTime(evaluationTime);
        } else {
            // 发生改变时通知
        }

        riskEvaluationPlanDao.save(plan);
    }

    private void processDistrictEvaluation(RiskEvaluationPlan plan) {
        RiskDistrict district = riskDistrictService.findById(plan.getRiskDistrictId());
        district.setRiskDistrictEvaluation(null);
        district.setEvaluationState(0);
        district.setRiskLevel(null);
        riskDistrictDao.save(district);
    }

    private Date getTodayEndTime() {
        Calendar c = Calendar.getInstance();
        c.set(Calendar.HOUR_OF_DAY, 23);
        c.set(Calendar.MINUTE, 59);
        c.set(Calendar.SECOND, 59);
        c.set(Calendar.MILLISECOND, 999);
        return c.getTime();
    }

    private Date getTodayStartTime() {
        Calendar c = Calendar.getInstance();
        c.set(Calendar.HOUR_OF_DAY, 0);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        c.set(Calendar.MILLISECOND, 0);
        return c.getTime();
    }


    @Scheduled(initialDelay=1000, fixedRate=300000)
    //隐患排查异常
    public void checkInspect(){
        BaseConfig config = baseConfigService.findFirstConfig(BaseConfigCodes.OPEN_GRADE_ALARM);
        if (config == null || "0".equals(config.getValue())) {
            return;
        }
        List<InspectExceptionAlarmMesage> inspectExceptionAlarmMesageList = inspectExceptionAlarmMesageMapper.findInspectExceptionAlarmMesageByState(0,null,null);
        if (!inspectExceptionAlarmMesageList.isEmpty()){
            for (InspectExceptionAlarmMesage inspectExceptionAlarmMesage : inspectExceptionAlarmMesageList) {
                // 隐患排查异常分级报警
                MhGradingAlarmDto mhGradingAlarmDto = new MhGradingAlarmDto();
                BeanUtils.copyProperties(inspectExceptionAlarmMesage,mhGradingAlarmDto);

                MhGradingAlarm mhGradingAlarm = mhGradingAlarmMapper.getMhGradingAlarmByOrgCode(mhGradingAlarmDto.getOrgCode());
                MhGradingAlarmBean mhGradingAlarmBean = new MhGradingAlarmBean();
                BeanUtils.copyProperties(mhGradingAlarm,mhGradingAlarmBean);
                String sdzrName = baseUserDao.getBaseUserNameById(Long.valueOf(mhGradingAlarm.getSdzr()));
                mhGradingAlarmBean.setSdzrName(sdzrName);
                String sdbmfzrName = baseUserDao.getBaseUserNameById(Long.valueOf(mhGradingAlarm.getSdbmfzr()));
                mhGradingAlarmBean.setSdbmfzrName(sdbmfzrName);
                String sdaqfzrName = baseUserDao.getBaseUserNameById(Long.valueOf(mhGradingAlarm.getSdaqfzr()));
                mhGradingAlarmBean.setSdaqfzrName(sdaqfzrName);
                String qyzyfzrName = baseUserDao.getBaseUserNameById(Long.valueOf(mhGradingAlarm.getQyzyfzr()));
                mhGradingAlarmBean.setQyzyfzrName(qyzyfzrName);
                String yhfzrName = baseUserDao.getBaseUserNameById(Long.valueOf(mhGradingAlarm.getYhfzr()));
                mhGradingAlarmBean.setYhfzrName(yhfzrName);

                mhGradingAlarmService.httpUrlGradingAlarmPush(mhGradingAlarmDto,mhGradingAlarmBean,0);
            }
        }
    }


//    @Scheduled(initialDelay=1000, fixedRate=300000)
//    //重大危险源报警
//    public void checkHardzard(){
//        List<MhAlarmMessage> mhAlarmMessageList = mhAlarmMessageDao.findByMhPointByState();
//        if (!mhAlarmMessageList.isEmpty()){
//            for (MhAlarmMessage mhAlarmMessage : mhAlarmMessageList) {
//                // 重大危险源报警分级报警
//                MhGradingAlarmDto mhGradingAlarmDto = new MhGradingAlarmDto();
//                BeanUtils.copyProperties(mhAlarmMessage,mhGradingAlarmDto);
//
//                MhGradingAlarm mhGradingAlarm = mhGradingAlarmMapper.getMhGradingAlarmByOrgCode(mhGradingAlarmDto.getOrgCode());
//                MhGradingAlarmBean mhGradingAlarmBean = new MhGradingAlarmBean();
//                BeanUtils.copyProperties(mhGradingAlarm,mhGradingAlarmBean);
//                String sdzrName = baseUserDao.getBaseUserNameById(Long.valueOf(mhGradingAlarm.getSdzr()));
//                mhGradingAlarmBean.setSdzrName(sdzrName);
//                String sdbmfzrName = baseUserDao.getBaseUserNameById(Long.valueOf(mhGradingAlarm.getSdbmfzr()));
//                mhGradingAlarmBean.setSdbmfzrName(sdbmfzrName);
//                String sdaqfzrName = baseUserDao.getBaseUserNameById(Long.valueOf(mhGradingAlarm.getSdaqfzr()));
//                mhGradingAlarmBean.setSdaqfzrName(sdaqfzrName);
//                String qyzyfzrName = baseUserDao.getBaseUserNameById(Long.valueOf(mhGradingAlarm.getQyzyfzr()));
//                mhGradingAlarmBean.setQyzyfzrName(qyzyfzrName);
//                String yhfzrName = baseUserDao.getBaseUserNameById(Long.valueOf(mhGradingAlarm.getYhfzr()));
//                mhGradingAlarmBean.setYhfzrName(yhfzrName);
//
//                mhGradingAlarmService.httpUrlGradingAlarmPush(mhGradingAlarmDto,mhGradingAlarmBean,1);
//            }
//        } else {
//            log.info("无重大危险源报警数据");
//        }
//    }

    /**
     * 分级报警新逻辑
     */
    @Scheduled(initialDelay=1000, fixedRate=300000)
    //重大危险源报警
    public void checkHardzard(){
        BaseConfig switchConfig = baseConfigService.findFirstConfig(BaseConfigCodes.OPEN_GRADE_ALARM);
        if (switchConfig == null || "0".equals(switchConfig.getValue())) {
            return;
        }
        MhAlarmLimitConfig config = alarmLimitConfigService.findOneConfig(null,null);
        if (config == null){
            return;
        }
        List<MhAlarmRecord> alarmRecords = alarmRecordService.findValidNoCode(config.getExceedTimes());
        if (CollectionUtils.isNotEmpty(alarmRecords)){
            alarmRecords.forEach(record -> {
                // 重大危险源报警分级报警
                MhGradingAlarmDto mhGradingAlarmDto = new MhGradingAlarmDto();
                mhGradingAlarmDto.setAlarmLevel(record.getMaxLevelName());
                mhGradingAlarmDto.setAlarmContent(record.getMaxDetail());
                mhGradingAlarmDto.setAlarmValue(record.getMaxValue());
                mhGradingAlarmDto.setTenentId(record.getTenentId());
                mhGradingAlarmDto.setOrgCode(record.getOrgCode());
                MhMonitoringPointBean point = mhMonitoringPointService.getById(record.getMonitoringPointId());
                mhGradingAlarmDto.setMonitoringPointName(point.getName());
                mhGradingAlarmDto.setPointDept(point.getResponsibleDept());
                mhGradingAlarmDto.setId(record.getAlarmMessageId());
                String alarmCode = mhGradingAlarmService.httpUrlGradingAlarmPush(mhGradingAlarmDto);
                if (StringUtils.isNotBlank(alarmCode)){
                    record.setExceedCount(0);
                    record.setAlarmCode(alarmCode);
                    record.setChangeTime(LocalDateTime.now());
                    record.setCodeLevelName(record.getMaxLevelName());
                    alarmRecordService.updateById(record);
                }
            });
        }else {
            log.info("无重大危险源报警数据");
        }
    }

    //隐患整改报警
    @Scheduled(initialDelay=1000, fixedRate=300000)
    public void checkWorkFlowProcess(){
        try {
            BaseConfig switchConfig = baseConfigService.findFirstConfig(BaseConfigCodes.OPEN_GRADE_ALARM);
            if (switchConfig == null || "0".equals(switchConfig.getValue())) {
                return;
            }
            List<WorkFlowProcess> workFlowProcessList = workFlowProcessService.findByBizNameList(WorkFlowConstants.APP_WORKFLOW_HIDDEN_DANGER);
            if (!workFlowProcessList.isEmpty()){
                for (WorkFlowProcess workFlowProcess:workFlowProcessList) {
                    MhGradingAlarm mhGradingAlarmByOrgCode = mhGradingAlarmMapper.getMhGradingAlarmByOrgCode(workFlowProcess.getOrgCode()); // 分级报警配置
                    String finishDateNameKey = workFlowTaskProcessListService.findProcessFormJsonKey(mhGradingAlarmByOrgCode.getFinishDateName(), workFlowProcess.getFormJson()); //完成日期名称
                    String hiddenDescriptionNameKey = workFlowTaskProcessListService.findProcessFormJsonKey(mhGradingAlarmByOrgCode.getHiddenDescriptionName(), workFlowProcess.getFormJson()); //隐患描述名称
                    String hiddenNameKey = workFlowTaskProcessListService.findProcessFormJsonKey(mhGradingAlarmByOrgCode.getHiddenName(), workFlowProcess.getFormJson()); //隐患名称
                    String reportTimeNameKey = workFlowTaskProcessListService.findProcessFormJsonKey(mhGradingAlarmByOrgCode.getReportTimeName(), workFlowProcess.getFormJson()); //上报时间
                    List<WorkFlowTask> workFlowTaskList = workFlowTaskDao.findScreenTaskByProcessIdAndStatus(workFlowProcess.getId(), WorkFlowStatusEnum.PROCESSING.getValue());
                    if (!workFlowProcessList.isEmpty()){
                        for (WorkFlowTask workFlowTask : workFlowTaskList) {
                            String formData = workFlowTask.getFormData();
                            if (StringUtils.isNotBlank(formData)){
                                String finishDateName = workFlowTaskProcessListService.findTaskFromDataValByKey(finishDateNameKey, formData);
                                if (StringUtils.isNotBlank(finishDateName)){
                                    Date parseDate = DateUtils.parseDate(finishDateName);
                                    boolean after = parseDate.after(new Date());
                                    if (after){
                                        String hiddenDescriptionName = workFlowTaskProcessListService.findTaskFromDataValByKey(hiddenDescriptionNameKey, formData);
                                        String hiddenName = workFlowTaskProcessListService.findTaskFromDataValByKey(hiddenNameKey, formData);
                                        String reportTimeName = workFlowTaskProcessListService.findTaskFromDataValByKey(reportTimeNameKey, formData);
                                        // 隐患排查异常分级报警
                                        MhGradingAlarmDto mhGradingAlarmDto = new MhGradingAlarmDto();
                                        BeanUtils.copyProperties(workFlowTask,mhGradingAlarmDto);
                                        mhGradingAlarmDto.setDetail(hiddenDescriptionName+";"+hiddenName+";"+reportTimeName);

                                        MhGradingAlarm mhGradingAlarm = mhGradingAlarmMapper.getMhGradingAlarmByOrgCode(mhGradingAlarmDto.getOrgCode());
                                        MhGradingAlarmBean mhGradingAlarmBean = new MhGradingAlarmBean();
                                        BeanUtils.copyProperties(mhGradingAlarm,mhGradingAlarmBean);
                                        String sdzrName = baseUserDao.getBaseUserNameById(Long.valueOf(mhGradingAlarm.getSdzr()));
                                        mhGradingAlarmBean.setSdzrName(sdzrName);
                                        String sdbmfzrName = baseUserDao.getBaseUserNameById(Long.valueOf(mhGradingAlarm.getSdbmfzr()));
                                        mhGradingAlarmBean.setSdbmfzrName(sdbmfzrName);
                                        String sdaqfzrName = baseUserDao.getBaseUserNameById(Long.valueOf(mhGradingAlarm.getSdaqfzr()));
                                        mhGradingAlarmBean.setSdaqfzrName(sdaqfzrName);
                                        String qyzyfzrName = baseUserDao.getBaseUserNameById(Long.valueOf(mhGradingAlarm.getQyzyfzr()));
                                        mhGradingAlarmBean.setQyzyfzrName(qyzyfzrName);
                                        String yhfzrName = baseUserDao.getBaseUserNameById(Long.valueOf(mhGradingAlarm.getYhfzr()));
                                        mhGradingAlarmBean.setYhfzrName(yhfzrName);

                                        mhGradingAlarmService.httpUrlGradingAlarmPush(mhGradingAlarmDto,mhGradingAlarmBean,2);
                                    }
                                }
                            }
                        }
                    }else {
                        log.info("无隐患整改报警数据");
                    }
                }
            } else {
                log.info("无隐患整改报警配置数据");
            }
        } catch (Exception e){
            log.error("隐患整改报警异常:"+e.getMessage());
        }

    }

}
